/* eslint-disable @typescript-eslint/no-explicit-any */
import { Nodes } from '@knno/dom';
import { jsxGen, JSXProps } from '@knno/dom/jsx';

export function isStr(v: unknown): v is string {
	return typeof v === 'string';
}
export function isBool(v: unknown): v is boolean {
	return typeof v === 'boolean';
}

export function isObject(v: unknown): v is object {
	return !!v && typeof v === 'object';
}

export function isNumber(v: unknown): v is number {
	return typeof v === 'number' && !isNaN(v);
}

export function isDate(v: unknown): v is Date {
	return v instanceof Date && !isNaN(Number(v));
}

export function isArray(v: unknown): v is Array<unknown> {
	return v instanceof Array;
}

// eslint-disable-next-line @typescript-eslint/ban-types
export function isFunc(v: unknown): v is Function {
	return typeof v === 'function';
}

export type AttrCheck = Record<string, ((v: unknown) => boolean) | boolean>;

export type On<Type, O extends Nodes> = {
	[key in keyof Type as `on${string & key}`]?: (this: O, evt: Type[key]) => void;
};

export function jsxBuild<T extends Nodes>(
	o: T,
	props: JSXProps<T>,
	children: (string | Nodes)[],
	attrCheck: AttrCheck
) {
	jsxGen(o, props, children, (attr, value) => {
		const fn = attrCheck[attr];
		if (typeof fn === 'function') {
			fn(value) && (o as any)[attr](value);
			return true;
		} else if (fn === true) {
			(o as any)[attr](value);
			return true;
		} else if (fn === false) {
			return true;
		} else return false;
	});
	return o;
}

export function renderIf(condition: boolean, renderer: (() => Nodes) | Nodes): Nodes {
	return condition ? (typeof renderer === 'function' ? renderer() : renderer) : new Nodes([]);
}
